home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 2010 April
/
PCWorld0410.iso
/
pluginy Firefox
/
5791
/
5791.xpi
/
chrome
/
flagfox.jar
/
content
/
flagfox.js
< prev
next >
Wrap
Text File
|
2009-02-04
|
22KB
|
550 lines
var FFpreferences = null;
var warningsThisSession = [];
var flagfoxstrings = null; // localized strings
var countrynames = null; // localized country names
var FlagfoxPollLoopID;
function Flagfox_startup()
{
try
{
window.removeEventListener("load", Flagfox_startup, false);
if (!document.getElementById("main-window"))
{
Components.utils.reportError("Flagfox warning: attempted to load into an invalid window");
return;
}
flagState.icon = document.getElementById("flagfox-icon");
if (!flagState.icon)
throw "Could not find icon";
countrynames = document.getElementById("flagfox-countrynames");
if (!countrynames || !countrynames.strings.hasMoreElements())
throw "Could not load country names";
flagfoxstrings = document.getElementById("flagfox-localizedstrings");
if (!flagfoxstrings || !flagfoxstrings.strings.hasMoreElements())
throw "Could not load localized strings";
FFpreferences = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
if (!FFpreferences)
throw "Could not fetch preferences service";
if (FlagfoxPollLoopID !== undefined)
throw "Flagfox is already loaded!";
window.addEventListener("unload", Flagfox_shutdown, false);
Flagfox_cleanupPrefs(); // Clear any pref entries from old versions
Flagfox_setIconPos(); // Place flag icon based on pref
Flagfox_prefObserver.register(); // Listen for preferences changes
Flagfox_dnsHandler.init(); // Fetch the services we need for DNS
Flagfox_loadIPDB(); // Load IPDB from "profileDir/extensionDir/db.dat"
// Check if add-on updates are enabled globally, or at least for Flagfox
if (!Flagfox_safeGetBoolPref("extensions.update.enabled") &&
!Flagfox_safeGetBoolPref("extensions.{1018e4d6-728f-4b20-ad56-37578a4de76b}.update.enabled"))
{
Flagfox_warning("flagfox.warn.updates", flagfoxstrings.getString("updateswarnmessage"));
}
}
catch (e)
{
if (e == "_setIconPos-abortStartup_")
return; // Failed to place icon; already shut down and don't need to show message
if (flagState.icon)
{
flagState.icon.src = "chrome://flagfox/content/icons/special/error.png";
flagState.icon.tooltipText = "Flagfox failed to load!";
}
Flagfox_shutdown();
Flagfox_error("Flagfox failed to load!",e);
return;
}
// Start polling loop
FlagfoxPollLoopID = setInterval(Flagfox_pollWindowURL, 250);
}
function Flagfox_shutdown()
{
window.removeEventListener("unload", Flagfox_shutdown, false);
clearInterval(FlagfoxPollLoopID);
Flagfox_dnsHandler.reset();
Flagfox_prefObserver.unregister();
Flagfox_closeIPDB();
}
var flagState =
{
url : "init",
host : "",
ip : "",
country : null,
icon : null,
newURL : function(newurl)
{
this.url = newurl;
this.host = "";
this.ip = "";
this.country = null;
},
IPisV6 : function()
{
return this.ip.indexOf(':') != -1; // a:b:c:d:e:f:g:h for IPv6 vs. a.b.c.d for IPv4
},
serverString : function()
{
if (this.host == this.ip)
return this.ip;
switch (textdirection) // via global.dtd
{
default:
case "ltr": return this.host + " (" + this.ip + ")";
/* I'm forced to work around Mozilla's automatic RTL punctuation flipping bugs here.
"host (ip)" shows as "(host (ip". The following should show as "host (ip)" for all instances.
There is no way to consistently show "(ip) host" in RTL, as it tries to flip the word order. */
case "rtl": return "(" + this.host + " (" + this.ip;
}
},
tooltipString : function()
{
return flagfoxstrings.getFormattedString( "tooltip", [this.serverString(),this.country[1]] );
}
};
var Flagfox_prefObserver =
{
branch : null, // the pref branch we're observing
register : function()
{
this.branch = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefService)
.getBranch("flagfox.");
this.branch.QueryInterface(Components.interfaces.nsIPrefBranch2);
this.branch.addObserver("", this, false);
},
unregister : function()
{
if (this.branch != null)
this.branch.removeObserver("", this);
},
observe : function(aSubject, aTopic, aData)
{
if (aTopic != "nsPref:changed")
return;
switch (aData)
{
case "usealticons":
Flagfox_setIconSrc();
break;
case "position.bar":
case "position.side":
Flagfox_setIconPos();
break;
case "warn.tld":
case "warn.proxy":
if (this.branch.getBoolPref(aData)==true)
warningsThisSession = []; // Reset list on pref reset
break;
}
}
};
function Flagfox_setIconPos()
{
try
{
function safeGetElementById(id)
{
var element = document.getElementById(id);
if (!element)
throw "Element does not exist: " + id;
return element;
}
function deleteElementById(id)
{
var node = document.getElementById(id);
if (!node)
return;
node.parentNode.removeChild(node);
if (document.getElementById(id) != null)
throw "Failed to delete element: " + id;
}
function wrapElementWith(node,type,id)
{
var wrapper = document.createElement(type);
wrapper.setAttribute("id",id);
wrapper.appendChild(node);
return wrapper;
}
/* Rather than detecting where the icon is and move it from there to its new location,
I move it into a temporary location and then delete both possible previous wrappers.
As a result, I can simply place the icon in the same generic way every time. */
var iconBox = safeGetElementById("flagfox-iconbox");
iconBox.hidden = true;
safeGetElementById("main-window").appendChild(iconBox);
if (!iconBox)
throw "Lost flagfox-iconbox in main-window";
// Cleanup any existing panels
deleteElementById("flagfox-statusbarpanel");
deleteElementById("flagfox-addressbarpanel");
var bar, panel, nextSibling;
var iconLoc = FFpreferences.getCharPref("flagfox.position.bar"); // What bar is it in?
var iconPos = FFpreferences.getCharPref("flagfox.position.side"); // Where in that bar is it?
switch (iconLoc)
{
case "statusbar": // Positions reversed in right-to-left locales
bar = safeGetElementById("status-bar");
panel = wrapElementWith(iconBox,"statusbarpanel","flagfox-statusbarpanel");
if (textdirection == "rtl") // via global.dtd
{
var flip = []; // Need to flip positioning to match strings
flip["LM"]="RM"; flip["L"]="R"; flip["R"]="L"; flip["RM"]="LM";
iconPos = flip[iconPos];
}
switch (iconPos)
{
case "LM":
nextSibling = bar.firstChild;
break;
case "L":
nextSibling = document.getElementById("statusbar-display");
if (!nextSibling)
nextSibling = bar.firstChild;
break;
case "R":
var popBlockBtn = document.getElementById("page-report-button");
if (!popBlockBtn)
popBlockBtn = document.getElementById("popupIcon"); // SeaMonkey 2 support (button has different ID)
nextSibling = popBlockBtn ? popBlockBtn.nextSibling : null ;
break;
case "RM":
nextSibling = null;
break;
}
break;
case "addressbar": // Positions _NOT_ reversed in right-to-left locales
bar = safeGetElementById("urlbar-icons");
panel = wrapElementWith(iconBox,"box","flagfox-addressbarpanel");
switch (iconPos)
{
case "LM": case "L": // REQUIRES FF3+
nextSibling = bar; // Will place icon to left of address field
bar = bar.parentNode; // Jump out of normal icon box
panel.style.marginLeft = "4px";
break;
case "R":
nextSibling = document.getElementById("star-button"); // If not FF3+ this'll be null => "RM"
if (nextSibling && nextSibling.parentNode.id != bar.id)
nextSibling = null; // Flock 2 support ("star-button" is not in "urlbar-icons")
break;
case "RM":
nextSibling = null;
break;
}
break;
}
if (nextSibling === undefined)
throw "Invalid position: " + iconLoc + "-" + iconPos;
// Make the placement
bar.insertBefore(panel,nextSibling);
iconBox.hidden = false;
}
catch (e)
{
Flagfox_shutdown(); // This window probably just lacks an address bar or status bar; Flagfox can't work in this window
if (String(e).substr(0,22) == "Element does not exist")
Components.utils.reportError("Flagfox warning: attempted to load icon into an unsupported window; \n" + e);
else
Flagfox_error("Error setting icon position",e);
throw "_setIconPos-abortStartup_"; // Abort startup sequence, if needed
}
}
function Flagfox_setIconSrc() // Applies to looked-up IPs only; others are done in the protocol switch
{
if (flagState.country == null)
return; // Flag is for local file or unknown site
var file;
switch (flagState.country[0])
{
case '-A': case '-B': case '-C':
file = "special/privateip";
break;
case '-L':
file = "special/localhost";
break;
case 'A1': case 'A2':
file = "special/anonymous";
break;
default:
var set = FFpreferences.getBoolPref("flagfox.usealticons") ? "flagset2/" : "flagset1/";
file = set + flagState.country[0].toLowerCase();
break;
}
flagState.icon.src = "chrome://flagfox/content/icons/" + file + ".png";
}
function Flagfox_pollWindowURL()
{
try
{
if (flagState.url != window.content.document.location.href)
{
flagState.newURL(window.content.document.location.href);
Flagfox_dnsHandler.reset(); // If we've changed pages before completing a lookup, then abort the old request and use this new one
switch (window.content.document.location.protocol)
{
case "file:":
flagState.icon.src = "chrome://flagfox/content/icons/special/localfile.png";
flagState.icon.tooltipText = flagfoxstrings.getString("localfile");
return; // Done
case "about:": case "chrome:": case "resource:": case "data:":
if (window.content.document.URL == "about:blank")
{ // Blank page gets its own icon and tooltip
flagState.icon.src = "chrome://flagfox/content/icons/special/blank.png";
flagState.icon.tooltipText = flagfoxstrings.getString("blankpage");
}
else
{
flagState.icon.src = "chrome://flagfox/content/icons/special/resource.png";
flagState.icon.tooltipText = flagfoxstrings.getString("localfile") + " (" + window.content.document.location.protocol + "//)";
}
return; // Done
default:
flagState.icon.src = "chrome://flagfox/content/icons/special/unknown.png";
flagState.icon.tooltipText = flagfoxstrings.getString("unknownsite");
break; // Consider unknown until we can look it up
}
flagState.host = window.content.document.location.hostname;
flagState.host = flagState.host.cropTrailingChar("."); // Get rid of root dot, if it's there
if (flagState.host == "")
{
Components.utils.reportError("Flagfox warning: no host"); // Not necessarily an error; show in error console if enabled
return;
}
if (Flagfox_dnsHandler.detectDNSProxy())
{
flagState.icon.src = "chrome://flagfox/content/icons/special/anonymous.png";
flagState.icon.tooltipText = flagfoxstrings.getString("proxywarntitle");
Components.utils.reportError("Flagfox warning: disabled due to proxy");
Flagfox_warning("flagfox.warn.proxy", flagfoxstrings.getString("proxywarnmessage"));
return; // Proxy in use for DNS; can't do a DNS lookup
}
// Idealy just hitting the DNS cache here
Flagfox_dnsHandler.resolveHost();
// Calls back to Flagfox_dnsHandler.onLookupComplete()
}
}
catch (e) { Components.utils.reportError("Flagfox EXCEPTION: " + Flagfox_parseException(e)); }
}
var Flagfox_dnsHandler =
{
dns : null, // DNS service
ios : null, // I/O service
proxy : null, // proxy service
thread : null, // this thread; onLookupComplete() must be called in this thread
request : null, // current DNS request in progress; cancel with this.reset()
init : function()
{
this.dns = Components.classes["@mozilla.org/network/dns-service;1"]
.getService(Components.interfaces.nsIDNSService);
this.ios = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
this.proxy = Components.classes["@mozilla.org/network/protocol-proxy-service;1"]
.getService(Components.interfaces.nsIProtocolProxyService);
var EQS = Components.classes["@mozilla.org/event-queue-service;1"];
if (EQS) // Firefox 1.5 - 2.0
{
EQS = EQS.getService(Components.interfaces.nsIEventQueueService);
this.thread = EQS.getSpecialEventQueue(EQS.CURRENT_THREAD_EVENT_QUEUE);
}
else // Firefox 3.0+
{
this.thread = Components.classes["@mozilla.org/thread-manager;1"]
.getService(Components.interfaces.nsIThreadManager)
.currentThread;
}
if (!this.thread)
throw "Could not fetch current thread for DNS handler";
},
reset : function()
{
if (this.request != null)
{
this.request.cancel(Components.results.NS_ERROR_ABORT); // calls onLookupComplete() with status=Components.results.NS_ERROR_ABORT
this.request = null;
}
},
detectDNSProxy : function() // Returns true if the current URL is set to have its DNS lookup proxied via SOCKS
{
var uri = this.ios.newURI(flagState.url, null, null);
var proxyinfo = this.proxy.resolve(uri, 0); // Finds proxy (shouldn't block thread; we already did this lookup to load the page)
return (proxyinfo != null) && (proxyinfo.flags & proxyinfo.TRANSPARENT_PROXY_RESOLVES_HOST);
// "network.proxy.socks_remote_dns" pref must be set to true for Firefox to set TRANSPARENT_PROXY_RESOLVES_HOST flag when applicable
},
resolveHost : function()
{
this.request = this.dns.asyncResolve(flagState.host, 0, this, this.thread);
},
onLookupComplete : function(nsrequest, nsrecord, status)
{
if (status == Components.results.NS_ERROR_ABORT)
return; // ignore this.reset()
this.request = null;
if (status != 0 || !nsrecord || !nsrecord.hasMore())
{
flagState.icon.src = "chrome://flagfox/content/icons/special/error.png";
flagState.icon.tooltipText = flagfoxstrings.getString("lookuperror");
var reason = (status==Components.results.NS_ERROR_UNKNOWN_HOST) ? ("Unknown host") : ("status="+status) ;
Components.utils.reportError("Flagfox error: DNS lookup fail: " + reason);
return; // IP not found in DNS
}
flagState.ip = nsrecord.getNextAddrAsString();
if (!flagState.IPisV6())
{
flagState.country = Flagfox_lookupIP(flagState.ip);
if (flagState.country == null)
{
flagState.icon.tooltipText = flagState.serverString() + " - " + flagfoxstrings.getString("unknownsite");
Components.utils.reportError("Flagfox warning: IP not in database");
return; // IP not in DB => Unknown site
}
}
else // IPv6 address was returned
{
if (flagState.ip == "::1") // Work around Vista stupidity
{
flagState.country = ['-L',countrynames.getString('-L')]; // localhost
}
else
{
flagState.icon.tooltipText = flagState.serverString() + " - " + flagfoxstrings.getString("unknownsite");
Components.utils.reportError("Flagfox warning: IPv6 not supported");
return; // DB is IPv4 only => Unknown site
}
}
// Set the image
Flagfox_setIconSrc();
// Set the tooltip
flagState.icon.tooltipText = flagState.tooltipString();
// Explain things to user if this IP is not in the same country as the domain's registration (common user confusion)
Flagfox_checkTLD();
}
};
function Flagfox_checkTLD()
{
try
{
var tld = flagState.host.truncateAfterLastChar(".");
if (tld.length != 2)
return;
var code = tld.toUpperCase(); // TLD tweaked to search in list
switch (code)
{ // Special cases:
case "UK": code = "GB"; break; // Different code for TLD vs in list
case "EU": return; // Don't tell users European countries aren't in Europe
case "TV": return; // Tuvalu sells its TLD use to media companies
}
var tldCountry = countrynames.getString(code); // Throws an exception if not found
if (tldCountry.length && flagState.country[0] != code)
{
Flagfox_warning("flagfox.warn.tld", flagfoxstrings.getFormattedString("tldwarnmessage",[flagState.country[1],"."+tld,tldCountry]));
}
} catch (e) {}
}
function Flagfox_warning(pref,message) // Shows a slide-down info bar (max once per session for each unique message)
{
if (!FFpreferences.getBoolPref(pref))
return; // Disabled by user
var messageID = Flagfox_hashString(message);
if (warningsThisSession.indexOf(messageID)!=-1)
return; // Shown before
warningsThisSession.push(messageID);
var notificationBox = window.getBrowser().getNotificationBox();
var priority = notificationBox.PRIORITY_WARNING_MEDIUM;
var buttons = [{ label: flagfoxstrings.getString("warnchecklabel"),
callback: function() { FFpreferences.setBoolPref(pref,false); }, // Don't show this again
accessKey: null, popup: null }];
notificationBox.appendNotification(message, pref, "chrome://flagfox/content/logo.png", priority, buttons);
}
function Flagfox_cleanupPrefs() // Wipes all Flagfox preferences that do not have defaults
{
/* Both the user and default branches contain the exact same list of pref names,
even if any default values don't exist or any user values equal the default. */
var prefService = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefService);
var defaultBranch = prefService.getDefaultBranch("flagfox.");
var userBranch = prefService.getBranch("flagfox.");
var prefsList = userBranch.getChildList("",{});
if (!prefsList.length)
throw "Could not load Flagfox preferences list";
for (var i in prefsList)
{ // Exception means no default exists and this pref is not in use
try { Flagfox_getPref(defaultBranch,prefsList[i]); }
catch (e) { userBranch.clearUserPref(prefsList[i]); }
}
}
function Flagfox_safeGetBoolPref(pref)
{
try { return FFpreferences.getBoolPref(pref); }
catch (e) { return false; }
}
String.prototype.cropTrailingChar = function(character)
{
return (this.charAt(this.length-1)==character) ? this.slice(0,this.length-1) : this.valueOf();
};
String.prototype.truncateAfterLastChar = function(character)
{
return this.substring(this.lastIndexOf(character)+1);
};